﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Linq;
using Scoreboard.Basement.ViewModels;
using Scoreboard.Interfaces;
using Scoreboard.Model;
using System.Collections.Generic;
using Microsoft.Practices.Composite.Presentation.Commands;
using Scoreboard.Basement;
using Scoreboard.Data;
using System.ServiceModel.DomainServices.Client;
using Microsoft.Practices.Composite.Events;
using Scoreboard.Basement.Events;

namespace Scoreboard.CommonViews
{
	public class AddResultDialogViewModel : DialogViewModel
	{
		private const int InvalidGroupId = -1;

		private IUserRepository _userRepository;
		private IGameRepository _gameRepository;

		private User _player;
		private User _mate;
		private User _opponent;
		private User _opponentMate;
		private string _playerScoreString;
		private string _opponentScoreString;
		private int _groupId;

		Action<InvokeOperation> _addResultCallback;

		public AddResultDialogViewModel(IUserRepository userRepository, IGameRepository gameRepository,
			Action<InvokeOperation> callback) : this(InvalidGroupId, null, userRepository, gameRepository, callback)
		{ 			
		}

		public AddResultDialogViewModel(int groupId, IEnumerable<User> players, 
			IUserRepository userRepository, IGameRepository gameRepository,
			Action<InvokeOperation> callback)
		{
			GroupId = groupId;
			HasCloseButton = true;
			InitialTitle = "Добавить результат 1 x 1";
			AlternateTitle = "Добавить результат 2 x 2";

			if (!IsViewSwitchAllowed)
			{
				InitialTitle = "Добавить результат";
				AlternateTitle = "Добавить результат";
			}

			WindowWidth = 600;

			AddResultCommand = new DelegateCommand<object>(AddResultCommandHandler);
			CancelCommand = new DelegateCommand<object>(CancelCommandHandler);
			NavigateToSinglesViewCommand = new DelegateCommand<object>(NavigateToSinglesViewCommandHandler);
			NavigateToDoublesViewCommand = new DelegateCommand<object>(NavigateToDoublesViewCommandHandler);

			if (WebContext.Current.IsUserRegistered)
			{
				Player = userRepository.CurrentUser;
			}

			_userRepository = userRepository;
			_gameRepository = gameRepository;

			_addResultCallback = callback;

			Players = players ?? _userRepository.GetPreloadedUsers()
									 .Where(user => user.IsAvailable)
									 .OrderBy(u => u.Name);
			
			PlayersWithoutCurrent = Players.Except(new[] { _userRepository.CurrentUser });	
			if (PlayersWithoutCurrent.Count() == 1)
			{
				Opponent = PlayersWithoutCurrent.Single();
			}

			FillCommands();
		}

		public ICommand NavigateToSinglesViewCommand { get; private set; }
		public ICommand NavigateToDoublesViewCommand { get; private set; }

		public IEnumerable<User> Players { get; private set; }
		public IEnumerable<User> PlayersWithoutCurrent { get; private set; }

		public ICommand AddResultCommand { get; private set; }
		public ICommand CancelCommand { get; private set; }

		public int GroupId
		{
			get
			{
				return _groupId;
			}
			set
			{
				_groupId = value;				
				FirePropertyChanged("IsViewSwitchAllowed");
			}
		}

		public string PlayerScoreString
		{
			get
			{
				return _playerScoreString;
			}
			set
			{
				_playerScoreString = value;
				FirePropertyChanged("PlayerScoreString");
			}
		}

		public string OpponentScoreString
		{
			get
			{
				return _opponentScoreString;
			}
			set
			{
				_opponentScoreString = value;
				FirePropertyChanged("OpponentScoreString");
			}
		}

		public User Player
		{
			get
			{
				return _player;
			}
			set
			{
				_player = value;
				FirePropertyChanged("Player");
			}
		}

		public User Mate
		{
			get
			{
				return _mate;
			}
			set
			{
				_mate = value;
				FirePropertyChanged("Mate");
			}
		}

		public User Opponent
		{
			get
			{
				return _opponent;
			}
			set
			{
				_opponent = value;
				FirePropertyChanged("Opponent");
			}
		}

		public User OpponentMate
		{
			get
			{
				return _opponentMate;
			}
			set
			{
				_opponentMate = value;
				FirePropertyChanged("OpponentMate");
			}
		}

		public bool IsViewSwitchAllowed
		{
			get
			{
				return GroupId == InvalidGroupId;
			}
		}

		private void AddResultCommandHandler(object parameter)
		{
			double participantScore;
			double opponentScore;

			if (!double.TryParse(PlayerScoreString, out participantScore)
				|| !double.TryParse(OpponentScoreString, out opponentScore))
			{
				return;
			}

			if (participantScore == opponentScore
				|| Math.Floor(participantScore) != participantScore
				|| Math.Floor(opponentScore) != opponentScore
				|| participantScore < 0
				|| opponentScore < 0
				|| participantScore > 99
				|| opponentScore > 99)
			{
				return;
			}

			if (Player == null || Opponent == null
				|| (!IsOnInitialPanel && (Mate == null || OpponentMate == null)))
			{
				return;
			}
			
			if (IsOnInitialPanel)
			{				
				if (Player == Opponent)
				{
					return;
				}
			}
			else
			{
				var players = new HashSet<User>(new[] { Player, Opponent, Mate, OpponentMate });
				if (players.Count != 4)
				{
					return;
				}
			}

			if (GroupId == InvalidGroupId)
			{
				User mateToPass = IsOnInitialPanel ? null : Mate;
				User opponentMateToPass = IsOnInitialPanel ? null : OpponentMate;

				_gameRepository.AddRatingResult(Player, mateToPass, Opponent, opponentMateToPass,
					participantScore, opponentScore, _addResultCallback);
			}
			else
			{
				_gameRepository.AddTournamentResult(Player, null, Opponent, null, participantScore,
					opponentScore, GroupId, _addResultCallback);				
			}

			CloseWindow();
		}		

		private void NavigateToSinglesViewCommandHandler(object parameter)
		{
			NavigateToInitialPanel();
		}

		private void NavigateToDoublesViewCommandHandler(object parameter)
		{
			NavigateToAlternatePanel();
		}

		private void CancelCommandHandler(object parameter)
		{
			CloseWindow();
		}

		private void FillCommands()
		{
			InitialCommands.Clear();
			AlternateCommands.Clear();			

			var addResultCommand = new UserCommand("Добавить", AddResultCommand);
			var cancelCommand = new UserCommand("Отмена", CancelCommand);

			InitialCommands.Add(addResultCommand);
			InitialCommands.Add(cancelCommand);
			AlternateCommands.Add(addResultCommand);
			AlternateCommands.Add(cancelCommand);
		}		
	}
}
